#pragma once
#include<vector>
#include"../Global.h"

//TODO:后续考虑如果采用线性映射，那么就需要以memory为基类，扩展出AM，SM，GSM子类，子类之间的不同在于起始地址偏移不同，但重写相同的api，内部计算地址的方式不同
//使用多态的方式可以很好地减少其他部分代码的改动
// class memory {
// public:
//     memory(int size) {
//         storage = new std::vector<char>(size);
//     }
//     ~memory() {
//         delete storage;
//     }
//     char load_1_byte(addr_size_t addr);
//     short load_2_bytes(addr_size_t addr);
//     int load_4_bytes(addr_size_t addr);
//     long long int load_8_bytes(addr_size_t addr);
//     bool store_1_byte(addr_size_t addr, char value);
//     bool store_2_bytes(addr_size_t addr, short value);
//     bool store_4_bytes(addr_size_t addr, int value);
//     bool store_8_bytes(addr_size_t addr, long long int value);
//     //TODO:为AM设计一套向量寄存器读写接口，连续16个字一起操作

// private:
//     std::vector<char> *storage; //以char 一个字节为单位来设计内存空间，具体的不同大小读写操作通过api来对外实现
// };

//使用线性映射的方式实现memory
class memory {
public:
    memory(int size, uint64_t start_offset) {
        memory_space = (uint8_t*)malloc(size * sizeof(uint8_t));
        offset = start_offset;
    }
    ~memory() {
        free(memory_space);
    }
    addr_size_t get_addr_offset(addr_size_t addr);
    uint8_t load_1_byte(addr_size_t addr);
    uint16_t load_2_bytes(addr_size_t addr);
    uint32_t load_4_bytes(addr_size_t addr);
    uint64_t load_8_bytes(addr_size_t addr);
    bool store_1_byte(addr_size_t addr, uint8_t value);
    bool store_2_bytes(addr_size_t addr, uint16_t value);
    bool store_4_bytes(addr_size_t addr, uint32_t value);
    bool store_8_bytes(addr_size_t addr, uint64_t value);

protected:
    uint8_t* memory_space; //以char 一个字节为单位来设计内存空间，具体的不同大小读写操作通过api来对外实现
    uint64_t    offset; //记录该内存的起始地址偏移
};

//TODO:为AM设计一套向量寄存器读写接口，连续16个字一起操作
class V_memory : public memory {
public:
    V_memory(int size, uint64_t start_offset) : memory(size, start_offset) {

    }
    ~V_memory() {}
    std::vector<uint64_t>* load_hw_vector(addr_size_t addr);
    std::vector<uint64_t>* load_hwu_vector(addr_size_t addr);
    std::vector<uint64_t>* load_w_vector(addr_size_t addr);
    bool    store_hw_vector(addr_size_t addr, std::vector<uint64_t>* value);
    bool    store_w_vector(addr_size_t addr, std::vector<uint64_t>* value);

private:

};